// poj2104
// 题意：区间k小。n<=100000, m<=5000
//
// 题解：全局二分。将数据和询问都弄到一起。然后不断进行二分。
//       假如当前二分到区间[l, r]，那么
//       对于队列中所有数据，用树状数组维护出小于等于mid的数，
//       对于询问，同样用树状数组得到这段区间小于等于mid的数，
//         1.如果这段区间小于等于mid的数的个数大于等于mid，就把它分到
//           [l, mid]这段区间（因为最终第k小的数肯定比mid小）
//         2.否则，就把它分到[mid+1, r]这段区间，并且把刚刚询问得到的
//           比mid小的数累加到这个询问的cur里（因为后面区间的mid肯定
//           也会有这些比mid'小的数）
//
//       对于数据也同样根据mid分到前一半区间和后一半区间。
//       然后要值得注意的trick是，不能每次把树状数组初始化，应该到过来
//       把加上去的数都减掉。
//
//       复杂度是T(n)=2*T(n/2)+O(nlogn), (这里n是n+m)
//       O(n)=n*log(n)^2
//
// run: $exec < input
// opt: 0
// flag: -g
#include <iostream>

long long const  inf = (1ll) << 30;
int const maxn = 200007;
int const maxm = 10007;
int tree[maxn];
int ans[maxm];
int n, m;

struct data
{
	int type; // 1 for data, 2 for query
	int v;
	int l, r, k; // find kth smallest value
	int cur; // current accumulation of less then k
	int one_query; // at one query the number less than current query mid value
	int id;
	int ans_id;
};

data da[maxn + maxm];
data part1[maxn + maxm], part2[maxn + maxm];

int lowbit(int x) { return x & -x; }

void bit_update(int id, int d)
{
	for (; id <= n; id += lowbit(id)) tree[id] += d;
}

int bit_sum(int id)
{
	int ret = 0;
	for (; id > 0; id -= lowbit(id)) ret += tree[id];
	return ret;
}

int negtive_mid(long long l, long long r)
{
	long long mid = (l + r) / 2;
	if (mid < 0) mid--;
	return mid;
}

void divide_and_conquer(int head, int tail, long long l, long long r)
{
	if (head > tail) return;
	if (l == r) {
		for (int i = head; i <= tail; i++)
			if (da[i].type == 2) ans[da[i].ans_id] = l;
		return;
	}
	long long mid = negtive_mid(l, r);
	for (int i = head; i <= tail; i++) {
		if (da[i].type == 1 && da[i].v <= mid) bit_update(da[i].id, 1);
		else if (da[i].type == 2) da[i].one_query = bit_sum(da[i].r) - bit_sum(da[i].l - 1);
	}
	for (int i = head; i <= tail; i++)
		if (da[i].type == 1 && da[i].v <= mid) bit_update(da[i].id, -1);
		else if (da[i].type == 2) break;
	int tot1 = 0, tot2 = 0;
	for (int i = head; i <= tail; i++)
		if (da[i].type == 2) {
			if (da[i].cur + da[i].one_query >= da[i].k)
				part1[++tot1] = da[i];
			else {
				da[i].cur += da[i].one_query;
				part2[++tot2] = da[i];
			}
		} else {
			if (da[i].v <= mid) part1[++tot1] = da[i];
			else part2[++tot2] = da[i];
		}
	for (int i = 1; i <= tot1; i++) da[head + i - 1] = part1[i];
	for (int i = 1; i <= tot2; i++) da[head + tot1 + i - 1] = part2[i];
	divide_and_conquer(head, head + tot1 - 1, l, mid);
	divide_and_conquer(head + tot1, head + tot1 + tot2 - 1, mid + 1, r);
}

int main()
{
	std::ios::sync_with_stdio(false);
	std::cin >> n >> m;
	int min = inf, max = -inf;
	for (int i = 1; i <= n; i++) {
		da[i].type = 1;
		da[i].id = i;
		std::cin >> da[i].v;
		min = std::min(min, da[i].v);
		max = std::max(max, da[i].v);
	}
	for (int i = 1; i <= m; i++) {
		da[n + i].type = 2;
		da[n + i].ans_id = i;
		std::cin >> da[n + i].l >> da[n + i].r >> da[n + i].k;
	}
	divide_and_conquer(1, n + m, -inf, inf);
	for (int i = 1; i <= m; i++)
		std::cout << ans[i] << '\n';
}

